// TextureManager
// 
// Author: Keith Maggio (KM)
//
// Purpose: Loads in textures into OpenGL

#ifndef _TEXTUREMANAGER_
#define _TEXTUREMANAGER_

#include <glee.h>
#include <gl.h>
#include <glu.h>
#include <glext.h>
#include <vector>

#define BAD_INDEX UINT_MAX

enum TextureParam {	CLAMP = GL_CLAMP_TO_EDGE, REPEAT = GL_REPEAT };

class TextureManager
{
private:
	struct TextureInfo
	{
		GLint	height, width;
		GLuint	ID;
		char	filename[MAX_PATH];

		TextureInfo();

		// Function Name:	Create
		// Purpose		:	Sets the data using the information passed in
		// Ins			:	file - The file to be used as a texture
		// Outs			:	Nothing.
		// Return		:	Nothing.
		void Create(const char* file);

		// Function Name:	Delete
		// Purpose		:	Clears the data for the current element
		// Ins			:	Nothing.
		// Outs			:	Nothing.
		// Return		:	Nothing.
		void Delete();
	};

private:
	std::vector<TextureInfo> TextureList;

private:

	//Private Instance
	static TextureManager m_Instance;

	//Constructor
	TextureManager();
	//Destructor
	~TextureManager();
	//Copy Constructor
	TextureManager(const TextureManager&);
	//Equals Operator
	TextureManager& operator=(const TextureManager&);

private:

	// Written by Richard Wright
	// Define targa header. This is only used locally.
#pragma pack(1)
	typedef struct
	{
		GLbyte	identsize;              // Size of ID field that follows header (0)
		GLbyte	colorMapType;           // 0 = None, 1 = paletted
		GLbyte	imageType;              // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle
		unsigned short	colorMapStart;          // First colour map entry
		unsigned short	colorMapLength;         // Number of colors
		unsigned char 	colorMapBits;   // bits per palette entry
		unsigned short	xstart;                 // image x origin
		unsigned short	ystart;                 // image y origin
		unsigned short	width;                  // width in pixels
		unsigned short	height;                 // height in pixels
		GLbyte	bits;                   // bits per pixel (8 16, 24, 32)
		GLbyte	descriptor;             // image descriptor
	} TGAHEADER;
#pragma pack(8)

	// Function Name:	LoadTGA
	// Purpose		:	Loads in a TGA file
	// Ins			:	fileName - the file to load
	//					Param - How to load it
	// Outs			:	Nothing.
	// Return		:	The filled-out TextureInfo
	TextureInfo LoadTGA(const char* fileName, TextureParam Param);

	//Written by Richard Wright
	// Function Name:	gltLoadTGA
	// Purpose		:	Loads in a TGA file
	// Ins			:	szFileName - The file to load
	// Outs			:	iWidth, iHeight - Dimensions of image
	//					iComponents, eFormat - Details of the TGA
	// Return		:	Byte info for the TGA
	GLbyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat);

public:

	// Function Name:	GetInstance
	// Purpose		:	Returns an Instance of the class
	// Ins			:	Nothing.
	// Outs			:	Nothing.
	// Return		:	TextureManager* to the Instance of the object
	static TextureManager* GetInstance()	{	return &m_Instance;		}

	// Function Name:	LoadTexture
	// Purpose		:	Returns an Instance of the class
	// Ins			:	fileName - File to load
	// Outs			:	Nothing.
	// Return		:	ID of the Texture
	int LoadTexture(const char* fileName, TextureParam param = CLAMP);
	int LoadTexture(const std::string& fileName, TextureParam param = CLAMP)
	{
		return LoadTexture(fileName.c_str(), param);
	}

	// Function Name:	UnloadTexture
	// Purpose		:	Unloads a texture from OpenGL
	// Ins			:	ID - The ID if the texture to unload
	// Outs			:	Nothing.
	// Return		:	Nothing.
	void UnloadTexture(GLuint ID);

	// Function Name:	GetTextureID
	// Purpose		:	Get a texture ID of a texture that was loaded in
	// Ins			:	fileName - Texture to find
	// Outs			:	Nothing.
	// Return		:	ID of texture, or -1 if it's not found
	int GetTextureID(const char* fileName);

	// Function Name:	Shutdown
	// Purpose		:	Shuts down the Texture manager and clears all the texture
	// Ins			:	Nothing.
	// Outs			:	Nothing.
	// Return		:	Nothing.
	void Shutdown();

	// Function Name:	GetTextureHeight
	// Purpose		:	Returns the Height of a texture found
	// Ins			:	ID - Texture to get info from
	// Outs			:	Nothing.
	// Return		:	Height of the texture, or -1 for failure.
	int GetTextureHeight(int ID)	
	{	
		if(ID < 0 || ID >= (int)TextureList.size())
		{
			return -1;
		}

		return TextureList[ID].height;	
	}

	// Function Name:	GetTextureWidth
	// Purpose		:	Returns the width of a texture found
	// Ins			:	ID - Texture to get info from
	// Outs			:	Nothing.
	// Return		:	width of the texture, or -1 for failure.
	int GetTextureWidth(int ID)	
	{	
		if(ID < 0 || ID >= (int)TextureList.size())
		{
			return -1;
		}

		return TextureList[ID].width;	
	}

};

#endif